package com.lambkit.module.upms.encrypt;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.lambkit.core.Lambkit;
import com.lambkit.core.LambkitResult;
import com.lambkit.core.exception.LambkitRenderException;
import com.lambkit.core.http.*;

import java.nio.charset.StandardCharsets;

public class RSAKeyRender extends Render {

	protected static String captchaName = "_lambkit_upms_key";

	protected boolean forIE = false;
	
	public RSAKeyRender forIE() {
		forIE = true;
		return this;
	}

	@Override
	public void render(IHttpContext context) {
		RSAKey key = new RSAKey();
		String uuid = IdUtil.randomUUID();
		
		//cache
		Lambkit.getCache().put(captchaName, uuid, key, 60 * 10);//10分钟

		//cookie
		context.setCookie(captchaName, uuid, -1, "/");
		context.getResponse().setHeader("Pragma","no-cache");
		context.getResponse().setHeader("Cache-Control","no-cache");
		context.getResponse().setDateHeader("Expires", 0);
		context.getResponse().setContentType("image/jpeg");
		
		//json
		String jsonText = JSONUtil.toJsonStr(LambkitResult.success().message(uuid).data(key.getPublicKey()));
		try {
			/**
			 * http://zh.wikipedia.org/zh/MIME
			 * 在wiki中查到: 尚未被接受为正式数据类型的subtype，可以使用x-开始的独立名称（例如application/x-gzip）
			 * 所以以下可能要改成 application/x-json
			 *
			 * 通过使用firefox测试,struts2-json-plugin返回的是 application/json, 所以暂不改为 application/x-json
			 * 1: 官方的 MIME type为application/json, 见 http://en.wikipedia.org/wiki/MIME_type
			 * 2: IE 不支持 application/json, 在 ajax 上传文件完成后返回 json时 IE 提示下载文件
			 */
			String contentType = this.forIE ? "text/html" : "application/json";
			contentType = contentType + ";charset=" + getEncoding();
			//context.getResponse().getCharacterEncoding();
			context.getResponse().setContentType(contentType);
			context.getResponse().write(jsonText.getBytes(StandardCharsets.UTF_8));
			context.getResponse().close();
		} catch (Exception exception) {
			throw new LambkitRenderException(exception);
		}
	}
	
	/**
	 * 解密用户输入的密码
	 * @param controller 控制器
	 * @param userInputString 用户输入的密码
	 * @return 返回密码明文
	 */
	public static String getPassword(IController controller, String userInputString) {
		userInputString = userInputString.replaceAll("%2B","+");
		String cacheKey = controller.getCookie(captchaName);
		if(StrUtil.isBlank(cacheKey)){
			cacheKey = controller.get("captchaName");
			if(StrUtil.isBlank(cacheKey)){
				return userInputString;
			}
		}
		return getPassword(cacheKey, userInputString);
	}
	
	/**
	 * 解密用户输入的密码
	 * @param request 控制器
	 * @param userInputString 用户输入的密码
	 * @return 返回密码明文
	 */
	public static String getPassword(IRequest request, String userInputString) {
		String cacheKey = getCookie(request, captchaName, null);
		if(StrUtil.isBlank(cacheKey)){
			return userInputString;
		}
		return getPassword(cacheKey, userInputString);
	}
	
	/**
	 * 解密用户输入的密码
	 * @param cacheKey 验证码 key，在不支持 cookie 的情况下可通过传参给服务端
	 * @param userInputString 用户输入的字符串
	 * @return 验证通过返回 true, 否则返回 false
	 */
	public static String getPassword(String cacheKey, String userInputString) {
		RSAKey rsakey = Lambkit.getCache().get(captchaName, cacheKey);
		if (rsakey != null) {
			return rsakey.decrypt(userInputString);
		}
		return userInputString;
	}
	
	/**
	 * Get cookie value by cookie name.
	 */
	public static String getCookie(IRequest request, String name, String defaultValue) {
		ICookie cookie = getCookieObject(request, name);
		return cookie != null ? cookie.getValue() : defaultValue;
	}
	
	public static ICookie getCookieObject(IRequest request, String name) {
		ICookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (ICookie cookie : cookies) {
				if (cookie.getName().equals(name)) {
					return cookie;
				}
			}
		}
		return null;
	}
}
